#ifndef DATASTORE_H_
#define DATASTORE_H_

#include "status.hxx"


class DbEnv;
class DataStoreImpl;
class Dbt;


#define INDEXARRAY_STATIC           0x0001
#define INDEXARRAY_DYNAMIC          0x0002
#define DATASEGMENT_IO              0x0004
#define DATASEGMENT_MEMORY          0x0008
#define DATASTORE_READONLY          0x0010


typedef std::string (MAPPINGFUNC)(Dbt&);

/**
 * A DataStore object manages a datastore(database), including cache,
 * patition, datasegments, index 
 */ 
class DataStore {

private:

    //cache size for reading, not supported yet
    uint32_t m_cacheSize;

    //index array size for a partition, should be >= the number of key in a partition 
    uint32_t m_indexArrayCapacity;

    //segment size, should be pow of 2
    uint32_t m_segmentCapacity;

    //mapping function between key and parition 
    MAPPINGFUNC* m_mapFunc;

    DbEnv* m_env;
    DataStoreImpl* m_datastoreImpl;

public:
    /**
     * Construct
     * @param: env   reference to dbenv object
     */ 
    DataStore(DbEnv& env);
    ~DataStore();

    /**
     * open a datastore
     * @param: dsName     datastore name
     * @param: cacheSize  cache size for reading, not supported yet (bytes)
     * @param: indexArrayCapacity  the size of index array, should be >= the
     * expected number of keys in a partition
     * @param: segCapacity  the capacity of data segment (bytes)
     * @param: mapFunc      a function pointer mapping function between key and parition
     * @param: flag         open flag, the values can be one of:
     * the combination of (DATASEGMENT_MEMORY or DATASEGMENT_IO) and
     * (INDEXARRAY_DYNAMIC or INDEXARRAY_STATIC) or DATASTORE_READONLY  
     */ 
    virtual DbStatus open(const std::string& dsName, 
            uint32_t cacheSize,
            uint32_t indexArrayCapacity, 
            uint32_t segCapacity, 
            MAPPINGFUNC* mapFunc, 
            uint32_t flag = 0);

    //close store
    virtual DbStatus close();

    virtual std::string getDsName();
    virtual std::string getDsPath();
    virtual uint32_t getIndexArrayCapacity();
    virtual uint32_t getSegCapacity();
    
    /**
     * Add a partition
     * @param: partitionName   the name of partition
     */
    virtual DbStatus addPartition(const std::string& partitionName); 
   
    //flush the index and the data of the store
    virtual DbStatus flush();

    //get value by key
    virtual DbStatus get(Dbt& key, Dbt& value);
    
    //put key-value pair
    virtual DbStatus put(Dbt& key, Dbt& value);
    
    //delete key-value pair by key
    virtual DbStatus del(Dbt& key);
};

#endif
